package cn.xyinping.pay.service.impl;

import cn.xyinping.basic.exception.MyException;
import cn.xyinping.order.domain.OrderPet;
import cn.xyinping.order.domain.OrderPetDetail;
import cn.xyinping.order.mapper.OrderPetDetailMapper;
import cn.xyinping.order.mapper.OrderPetMapper;
import cn.xyinping.pay.domain.AlipayInfo;
import cn.xyinping.pay.domain.PayBill;
import cn.xyinping.pay.domain.PayFlow;
import cn.xyinping.pay.dto.AlipayDto;
import cn.xyinping.pay.mapper.AlipayInfoMapper;
import cn.xyinping.pay.mapper.PayBillMapper;
import cn.xyinping.pay.mapper.PayFlowMapper;
import cn.xyinping.pay.service.IPayService;
import cn.xyinping.pet.domain.Pet;
import cn.xyinping.pet.mapper.PetMapper;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 27266
 * @desrciption 宠物支付
 * @date 2021/11/9
 */
@Service
public class PayServiceImpl implements IPayService {
    @Autowired
    private AlipayInfoMapper alipayInfoMapper;
    @Autowired
    private PayBillMapper payBillMapper;
    @Autowired
    private PayFlowMapper payFlowMapper;
    @Autowired
    private OrderPetMapper orderPetMapper;
    @Autowired
    private OrderPetDetailMapper orderPetDetailMapper;
    @Autowired
    private PetMapper petMapper;

    // 支付申请
    @Override
    public String applyPay(String orderNo) {
        // 1 参数非空校验
        if (StringUtils.isEmpty(orderNo)) {
            throw new MyException("订单号不能为空");
        }
        // 2. 加载支付宝配置
        AlipayInfo alipayInfo = alipayInfoMapper.loadFarst();
        if(alipayInfo == null){
            throw new MyException("支付宝配置无效");
        }
        // 3. 查询支付单
        PayBill payBill = payBillMapper.loadByorderNo(orderNo);
        if(payBill == null){
            throw new MyException("支付单无效");
        }
        // 4. 发起支付请求
        Factory.setOptions(alipayInfo.getOptions()); // 设置参数
        try {
            // 发起API调用：电脑网站的两种方式
            String returnUrl = String.format("http://127.0.0.1/pay-success.html?orderNo=%s",orderNo);
//            String returnUrl = String.format(alipayInfo.getReturnUrl(),orderNo);
            AlipayTradePagePayResponse response  = Factory.Payment.Page().pay(
                    payBill.getDigest(), // 标题
                    payBill.getUnionPaySn(), // 单号
                    payBill.getMoney().toString(), // 金额
                    returnUrl); // 同步回调地址

            System.out.println(response.body);
            // 处理响应或异常
            if (ResponseChecker.success(response )) {
                System.out.println("调用成功");
                //5.处理结果
                return response.body;
            } else {
                System.err.println("调用失败，原因：" );
            }
        } catch (Exception e) {
            System.err.println("调用遭遇异常，原因：" + e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }

        return "支付申请失败";

    }
    // 支付结果处理
    @Override
    public String alipayNotify(AlipayDto dto) {
        // 1. 校验参数非空
        if(dto==null){
            throw new MyException("参数不能为空");
        }
        // 2. 验证签名
        // 把对象转成json格式字符串
        String string = JSON.toJSONString(dto);
        // 把字符串转换为Map
        Map<String,String> parameters = JSON.parseObject(string, Map.class);
        // 支付宝配置
        AlipayInfo alipayInfo = alipayInfoMapper.loadFarst();
//        Factory.setOptions(alipayInfo.getOptions());
        try {
            Boolean verifySignSuccess = Factory.Payment.Common().verifyNotify(parameters);
            if(!verifySignSuccess){
                System.out.println("验证签名失败...");
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 判断订单号是否为空
        String out_trade_no = dto.getOut_trade_no();
        if(StringUtils.isEmpty(out_trade_no)){
            return "fail";
        }
        // 判断金额是否为空
        PayBill payBill = payBillMapper.loadByorderNo(out_trade_no);
        if(payBill==null){
            return "fail";
        }
        //  3.防止支付结果重复处理 ,支付宝会回调N次
        if(payBill.getState().intValue() != PayBill.SATET_WAIT_PAY){
            //支付已经被处理
            return "success";
        }
        // 对比金额
        BigDecimal decimal = new BigDecimal(dto.getTotal_amount());
        if(payBill.getMoney().compareTo(decimal) !=0){
            System.out.println("无效金额");
            return "fail";
        }
        String appId = dto.getApp_id();
        if(StringUtils.isEmpty(appId)||!appId.equals(alipayInfo.getAppid())){
            System.out.println("无效的金额");
            return "fail";
        }
        // 3. 保存支付流水PayFlow
        PayFlow flow = new PayFlow();
        BeanUtils.copyProperties(dto, flow);
        payFlowMapper.add(flow);
        // 4. 修改支付宝状态payBill
        if(dto.isTradeWit()){
            System.out.println("支付中");
            return "fail";
        }
        // 业务单
        OrderPet orderPet = orderPetMapper.loadByOrderNo(out_trade_no);
        /**
         List<Long> petIds = new ArrayList<>(details.size());
         details.forEach(detail->{
         petIds.add(detail.getPetId());
         });
         */
         if(orderPet==null){
             System.out.println("单号无效");
             return "fail";
         }
         // 订单明细
        List<OrderPetDetail> details = orderPetDetailMapper.loadByOrderNo(out_trade_no);
        // jdk8新特性：查询宠物ID
        List<Long> petIds = details.stream().map(detail -> detail.getPetId()).collect(Collectors.toList());
        // 查询所有上架的宠物
        List<Pet> pets = petMapper.findByIds(petIds, Pet.STATE_ONLINE);
        // 支付成功
        if(dto.isTradeSuccess()){
            // 成功
            payBill.setState(PayBill.SATET_SUCCESS_PAY);
            //支付成功，待发货
            orderPet.setState(OrderPet.STATE_SUCCESS_PAY);
        } else if(dto.isTradeExpire()){ // 超时
            payBill.setState(PayBill.SATET_OUTTIME_OR_RETURN);
            orderPet.setState(OrderPet.STATE_PAY_OUTTIME_CANCEL);
            // 6.如果是失败，宠物库存退回
            pets.forEach(pet -> {
                // 严格来说应该加订单明细中的count
                pet.setStore_number(pet.getStore_number()+1);
                petMapper.update(pet);
            });
        } else {
            System.out.println("失败");
            return "fail";
        }
        //最后支付处理时间
        payBill.setLastPayTime(new Date());
        payBillMapper.update(payBill);
        orderPetMapper.update(orderPet);
        return "success";
    }


}
